From eadf155ee317140c416c3f7b07fa06f9688dc9fb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 21 Jul 2005 14:15:35 +0000 Subject: [PATCH] Fix problem of can not create two or more vmx guest. The original gdb server patch will cause the new vmx guest break the=20 old one. This patch make the arch_set_guest_info modify the correct vmcs and also skip modifying during creating. Signed-off-by: Xiaofeng Ling ^ Signed-off-by: Arun Sharma --- xen/arch/x86/domain.c | 12 ++++++------ xen/arch/x86/vmx_io.c | 16 ++++++++++++++-- xen/arch/x86/vmx_vmcs.c | 29 +++++++++++++++++++++++++++++ xen/include/asm-x86/vmx.h | 4 ++++ xen/include/asm-x86/vmx_vmcs.h | 2 ++ 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 609822d40a..d28e5683f7 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -417,12 +417,12 @@ int arch_set_info_guest( /* Ensure real hardware interrupts are enabled. */ v->arch.guest_context.user_regs.eflags |= EF_IE; - } else { - __vmwrite(GUEST_RFLAGS, v->arch.guest_context.user_regs.eflags); - if (v->arch.guest_context.user_regs.eflags & EF_TF) - __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); - else - __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + } + else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + { + return modify_vmcs( + &v->arch.arch_vmx, + &v->arch.guest_context.user_regs); } if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 83e79d6bba..cbc88deb8b 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -39,14 +39,20 @@ #ifdef CONFIG_VMX #if defined (__i386__) -static void load_cpu_user_regs(struct cpu_user_regs *regs) +void load_cpu_user_regs(struct cpu_user_regs *regs) { /* * Write the guest register value into VMCS */ __vmwrite(GUEST_SS_SELECTOR, regs->ss); __vmwrite(GUEST_RSP, regs->esp); + __vmwrite(GUEST_RFLAGS, regs->eflags); + if (regs->eflags & EF_TF) + __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + else + __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + __vmwrite(GUEST_CS_SELECTOR, regs->cs); __vmwrite(GUEST_RIP, regs->eip); } @@ -175,11 +181,17 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r } } #else -static void load_cpu_user_regs(struct cpu_user_regs *regs) +void load_cpu_user_regs(struct cpu_user_regs *regs) { __vmwrite(GUEST_SS_SELECTOR, regs->ss); __vmwrite(GUEST_RSP, regs->rsp); + __vmwrite(GUEST_RFLAGS, regs->rflags); + if (regs->rflags & EF_TF) + __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + else + __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + __vmwrite(GUEST_CS_SELECTOR, regs->cs); __vmwrite(GUEST_RIP, regs->rip); } diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index a8a01c7808..b7277e08c9 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -453,6 +453,35 @@ int construct_vmcs(struct arch_vmx_struct *arch_vmx, return -EINVAL; } + if (regs->eflags & EF_TF) + __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + else + __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + + return 0; +} + +/* + * modify guest eflags and execption bitmap for gdb + */ +int modify_vmcs(struct arch_vmx_struct *arch_vmx, + struct cpu_user_regs *regs) +{ + int error; + u64 vmcs_phys_ptr, old, old_phys_ptr; + vmcs_phys_ptr = (u64) virt_to_phys(arch_vmx->vmcs); + + old_phys_ptr = virt_to_phys(&old); + __vmptrst(old_phys_ptr); + if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) { + printk("modify_vmcs: load_vmcs failed: VMCS = %lx\n", + (unsigned long) vmcs_phys_ptr); + return -EINVAL; + } + load_cpu_user_regs(regs); + + __vmptrld(old_phys_ptr); + return 0; } diff --git a/xen/include/asm-x86/vmx.h b/xen/include/asm-x86/vmx.h index 952bb01cfc..36ef003de8 100644 --- a/xen/include/asm-x86/vmx.h +++ b/xen/include/asm-x86/vmx.h @@ -447,4 +447,8 @@ static inline int iopacket_port(struct domain *d) return get_sp(d)->sp_global.eport; } +/* Prototypes */ +void load_cpu_user_regs(struct cpu_user_regs *regs); +void store_cpu_user_regs(struct cpu_user_regs *regs); + #endif /* __ASM_X86_VMX_H__ */ diff --git a/xen/include/asm-x86/vmx_vmcs.h b/xen/include/asm-x86/vmx_vmcs.h index 65debd3f6e..93cdb48127 100644 --- a/xen/include/asm-x86/vmx_vmcs.h +++ b/xen/include/asm-x86/vmx_vmcs.h @@ -97,6 +97,8 @@ int load_vmcs(struct arch_vmx_struct *, u64); int store_vmcs(struct arch_vmx_struct *, u64); int construct_vmcs(struct arch_vmx_struct *, struct cpu_user_regs *, struct vcpu_guest_context *, int); +int modify_vmcs(struct arch_vmx_struct *arch_vmx, + struct cpu_user_regs *regs); #define VMCS_USE_HOST_ENV 1 #define VMCS_USE_SEPARATE_ENV 0 -- 2.30.2